load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("@rules_python//python:defs.bzl", "py_test")
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
load("//:requirements.bzl", "all_data_requirements", "all_requirements", "all_whl_requirements", "requirement")

# This rule adds a convenient way to update the requirements.txt
# lockfile based on the requirements.in.
compile_pip_requirements(
    name = "requirements",
    src = "requirements.in",
)

# The requirements.bzl file is using the hub repo to access packages via the
# `requirement` macro and when the requirements.bzl is vendored, the hub
# repo won't be present. As a result, we have to adjust the label scheme in
# the requirements.bzl to make sure that they continue to work.
genrule(
    name = "requirement_bzl",
    srcs = ["@pip_deps_to_be_vendored//:requirements.bzl"],
    outs = ["requirements.clean.bzl"],
    cmd = " | ".join([
        "cat $<",
        # Substitute the name of the hub to ensure that the dependencies do
        # not require the hub repo initialized in the WORKSPACE.
        "sed -e 's/pip_deps_to_be_vendored/my_project_pip_deps_vendored/g'",
        # Change the labels from using the hub repo to using the spoke repos
        # directly.
        "sed -e 's|//\\([^:]*\\):pkg|_\\1//:pkg|g'",
        "sed -e 's|//\\([^:]*\\):whl|_\\1//:whl|g'",
        "sed -e 's|//\\([^:]*\\):data|_\\1//:data|g'",
        # Change the convenience macros to use the same naming.
        "sed -e 's|//{}:{}|_{}//:{}|g' >$@",
    ]),
)

write_file(
    name = "gen_update",
    out = "update.sh",
    content = [
        # This depends on bash, would need tweaks for Windows
        "#!/usr/bin/env bash",
        # Bazel gives us a way to access the source folder!
        "cd $BUILD_WORKSPACE_DIRECTORY",
        "cp -fv bazel-bin/requirements.clean.bzl requirements.bzl",
    ],
)

sh_binary(
    name = "vendor_requirements",
    srcs = ["update.sh"],
    data = [":requirement_bzl"],
)

# Similarly ensures that the requirements.bzl file is updated
# based on the requirements.txt lockfile.
diff_test(
    name = "test_vendored",
    failure_message = "Please run:  bazel run //:vendor_requirements",
    file1 = "requirements.bzl",
    file2 = "requirement_bzl",
)

py_test(
    name = "test_dependency_usage",
    srcs = ["test_dependency_usage.py"],
    deps = [
        requirement("requests"),
    ],
)

build_test(
    name = "test_requirement_lists",
    targets = all_requirements + all_whl_requirements + all_data_requirements,
)
